package cn.it.shop.action;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import cn.it.shop.model.Category;


//public class CategoryAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{ 
//public class CategoryAction extends BaseAction implements ModelDriven<Category>{ 
@Controller("categoryAction")
@Scope("prototype")
public class CategoryAction extends BaseAction<Category>{


	/*
	 * 应该是account中的category懒加载的问题，你查的是category，然后即left joint fetch了account，
	 * 所以当你查category的时候，category中的account也拿到了，这没问题。但是你自动生成表的时候，由于外键关系，
	 * 你的account中也会生成category，这个account中的category它就拿不到了。所以struts2在将数据转json的时候，
	 * 遵循下面这个流程：转category(正常)----->转category中的account(正常,因为你left join fetch了category)
	 * ---->转category中的account中的category(出错，因为account中有category属性，它就会去转)。
	 * 给你提供三种办法：1. 将account中的category设置为fetch = FetchType.EAGER，但是不建议这么做，会影响性能；
	 * 2. 因为我们不需要从account中的拿category，所以在Account类中干掉Category和它的set,get方法；
	 * 3. 如果你不想干掉Account中的Category，你也可以在struts.xml的黑名单配置中加上rows\d+\.account\.categories试试，
	 * 告诉struts2转json时转到account就行了，别再转account中的category了。
	 * 这样应该就能解决你遇到的问题了，建议三种方法都试试，加深理解，掌握背后原理最重要~~
	 */
	public String queryJoinAccount(){
		
	       //用来存储分页的数据  
        pageMap = new HashMap<String, Object>();  
         
        //根据关键字和分页的参数查询相应的数据。这个方法我们在Service中写过了，当时完成级联查询  
        List<Category> categoryList = categoryService.queryJoinAccount(model.getType(), page, rows);  
        pageMap.put("rows", categoryList); //存储为JSON格式，从上一节的json文件可以看出，一个key是total,一个key是rows，这里先把rows存放好  
        //根据关键字查询总记录数  
        Long total = categoryService.getCount(model.getType()); //这个方法没写，我们等会儿去Service层完善一下  
//      System.out.println(total);  
        pageMap.put("total", total); //存储为JSON格式，再把total存放好  
  
        return "jsonMap";  
	}
	
	
	
	public String deleteByIds(){
		
		categoryService.deleteByIds(ids);
		
		inputStream = new ByteArrayInputStream("true".getBytes()); //将"true"的字节存到流inputStream中  
		
        return "stream";  
	}
	
	public String query() {
		jsonList = categoryService.query();
		return "jsonList";
	}
	
	public void save(){
		System.out.println(model);
		categoryService.save(model);
	}
	
	
	public void update(){
		System.out.println(model);
		categoryService.update(model);
	}
	
	
	
	
	
	
	
	
	
//	 private Category category;//设置一个私有成员变量接收url带过来的参数，注意下面要写好get和set方法  
	 /* 3.3
	  * 有个成员变量category，这是个POJO，定义这个变量并写好set和get方法是为了JSP页面可以通过url后面附带参数传进来，
	  * 参数是category对象中的属性，比如id，type等，但是url中的参数必须写成category.id、category.type等。
	  * 这样struts会自动将这写参数注入到category对象中，然后我们就可以直接使用这个category对象了，
	  * 但是这样有点繁琐。我们可以使用ModelDriven来更方便的解决。
	  */
	 
	 
	 /*
	  * 3.5
	  * 到这里，还有一个看着不爽的地方，就是categoryService这个成员变量，它一直存在在CategoryAction里，
	  * 因为CategoryAction中有用到categoryService对象中的方法，所以必须得创建这个对象，并且有set方法才能注入进来。
	  * 这就导致一个弊端：如果很多Action都需要使用categoryService的话，那就必须在它们的Action里创建这个对象和set方法，
	  * 而且，如果一个Action中要使用好几个不同的service对象，那就得全部创建，这样就变得很冗杂。
	  */
	 
//	 @Resource(name="CategoryService")
//	 private CategoryService categoryService; //设置categoryService是为了很直观的看出与Spring整合前后的不同  
     
	 
//	    public void setCategoryService(CategoryService categoryService) {  
//	    	System.out.println("注入了categoryService");
//	        this.categoryService = categoryService;  
//	    }  
	      
//	    public String update() {  
//	        System.out.println("----update----");  
//	        System.out.println(categoryService); //整合前后输出不同  
//	        categoryService.update(model); //新加一条语句，来更新数据库  
//	        return "index";  
//	    }  
	      
//	    public String save() {  
//	        System.out.println("----save----");  
//	        System.out.println(categoryService);//整合前后输出不同  
//	        return "index";  
//	    }

	    
	   
	    /*
	     * 3.2
	     * 还是上一节整合三大框架时的CategoryAction类，我们在里面加了一个query方法，在该方法中，我们通过向request域、session域和application域
	     * 中存入查询的结果。第一种方法是直接使用ActionContext来实现，不需要实现任何接口，但是代码量较大；第二种方法通过实现RequestAware、
	     * SessionAware和ApplicationAware接口，实现该接口的三个抽象方法把request、session和application注入进来，然后赋给相应的成员变量中，
	     * 这样就可以在query方法中向域中存放查询结果了。这代码量貌似比第一种方法更大……但是我们可以抽取
	     */
//	    public String query() {  
	         //解决方案一，采用相应的map取代原来的内置对象，这样与jsp没有依赖，但是代码量比较大  
     //	    ActionContext.getContext().put("categoryList", categoryService.query()); //放到request域中  
	 //     ActionContext.getContext().getSession().put("categoryList", categoryService.query()); //放到session域中  
	 //     ActionContext.getContext().getApplication().put("categoryList", categoryService.query()); //放到application域中  
	          
	        //解决方案二，实现相应的接口(RequestAware,SessionAware,ApplicationAware)，让相应的map注入  
//	        request.put("categoryList", categoryService.query());   
//	        session.put("categoryList", categoryService.query());   
//	        application.put("categoryList", categoryService.query());   
//	        return "index";  
////	    } 	    
	    
	    
	
//		public Category getCategory() {
//			return category;
//		}
//
//		public void setCategory(Category category) {
//			this.category = category;
//		}
	    
	    
	    
	    
	    /*
	     * 3.4
	     * 实现ModelDriven后，不需要再有get和setCategory的方法
	     * 同样把它抽离到BaseAction中	
	     */
//		@Override
//		public Category getModel() {
//			if(category!=null){
//				category = new Category();
//			}
//		
//			return category;
//		}	    

	    
}
